/*! * This program is free software; you can redistribute it and/or modify it under the * terms of the GNU Lesser General Public License, version 2.1 as published by the Free Software * Foundation. * * You should have received a copy of the GNU Lesser General Public License along with this * program; if not, you can obtain a copy at http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html * or from the Free Software Foundation, Inc., * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. * * This program is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; * without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. * See the GNU Lesser General Public License for more details. * * Copyright (c) 2002-2016 Pentaho Corporation.. All rights reserved. */ package org.pentaho.mantle.client.dialogs.scheduling; import java.util.Date; import java.util.List; import org.pentaho.gwt.widgets.client.dialogs.IDialogCallback; import org.pentaho.gwt.widgets.client.dialogs.MessageDialogBox; import org.pentaho.gwt.widgets.client.dialogs.PromptDialogBox; import org.pentaho.gwt.widgets.client.utils.TimeUtil; import org.pentaho.gwt.widgets.client.utils.TimeUtil.DayOfWeek; import org.pentaho.gwt.widgets.client.utils.TimeUtil.MonthOfYear; import org.pentaho.gwt.widgets.client.utils.TimeUtil.WeekOfMonth; import org.pentaho.gwt.widgets.client.utils.string.StringUtils; import org.pentaho.gwt.widgets.client.wizards.AbstractWizardDialog; import org.pentaho.gwt.widgets.client.wizards.IWizardPanel; import org.pentaho.mantle.client.dialogs.scheduling.RecurrenceEditor.DailyRecurrenceEditor; import org.pentaho.mantle.client.dialogs.scheduling.RecurrenceEditor.MonthlyRecurrenceEditor; import org.pentaho.mantle.client.dialogs.scheduling.RecurrenceEditor.WeeklyRecurrenceEditor; import org.pentaho.mantle.client.dialogs.scheduling.RecurrenceEditor.YearlyRecurrenceEditor; import org.pentaho.mantle.client.dialogs.scheduling.ScheduleEditor.DurationValues; import org.pentaho.mantle.client.dialogs.scheduling.ScheduleEditor.ScheduleType; import org.pentaho.mantle.client.messages.Messages; import org.pentaho.mantle.client.workspace.BlockoutPanel; import org.pentaho.mantle.client.workspace.JsBlockStatus; import org.pentaho.mantle.client.workspace.JsJob; import org.pentaho.mantle.client.workspace.JsJobParam; import org.pentaho.mantle.client.workspace.JsJobTrigger; import org.pentaho.mantle.login.client.MantleLoginDialog; import com.google.gwt.core.client.GWT; import com.google.gwt.core.client.JavaScriptObject; import com.google.gwt.core.client.JsArrayInteger; import com.google.gwt.core.client.JsArrayString; import com.google.gwt.core.client.JsonUtils; import com.google.gwt.event.dom.client.ClickEvent; import com.google.gwt.event.dom.client.ClickHandler; import com.google.gwt.event.dom.client.KeyCodes; import com.google.gwt.http.client.Request; import com.google.gwt.http.client.RequestBuilder; import com.google.gwt.http.client.RequestCallback; import com.google.gwt.http.client.RequestException; import com.google.gwt.http.client.Response; import com.google.gwt.i18n.client.DateTimeFormat; import com.google.gwt.i18n.client.DateTimeFormat.PredefinedFormat; import com.google.gwt.json.client.JSONArray; import com.google.gwt.json.client.JSONNull; import com.google.gwt.json.client.JSONNumber; import com.google.gwt.json.client.JSONObject; import com.google.gwt.json.client.JSONParser; import com.google.gwt.json.client.JSONString; import com.google.gwt.user.client.Random; import com.google.gwt.user.client.Timer; import com.google.gwt.user.client.Window; import com.google.gwt.user.client.rpc.AsyncCallback; import com.google.gwt.user.client.ui.DockPanel; import com.google.gwt.user.client.ui.Widget; /** * @author wseyler * */ public class ScheduleRecurrenceDialog extends AbstractWizardDialog { private static final String HOUR_MINUTE_SECOND = "h:mm:ss a"; private final String moduleBaseURL = GWT.getModuleBaseURL(); private final String moduleName = GWT.getModuleName(); private final String contextURL = moduleBaseURL.substring( 0, moduleBaseURL.lastIndexOf( moduleName ) ); protected String filePath; protected String outputLocation; protected String scheduleName; private IDialogCallback callback; boolean isBlockoutDialog = false; private ScheduleEmailDialog scheduleEmailDialog; private ScheduleParamsDialog scheduleParamsDialog; protected ScheduleEditorWizardPanel scheduleEditorWizardPanel; protected JsJob editJob = null; private Boolean done = false; private boolean hasParams = false; private boolean isEmailConfValid = false; private boolean showSuccessDialog = true; private ScheduleEditor scheduleEditor; private PromptDialogBox parentDialog; private boolean newSchedule = true; public ScheduleRecurrenceDialog( PromptDialogBox parentDialog, JsJob jsJob, IDialogCallback callback, boolean hasParams, boolean isEmailConfValid, final ScheduleDialogType type ) { super( type, type != ScheduleDialogType.BLOCKOUT ? Messages.getString( "editSchedule" ) : Messages.getString( "editBlockoutSchedule" ), null, false, true ); //$NON-NLS-1$ //$NON-NLS-2$ isBlockoutDialog = ( type == ScheduleDialogType.BLOCKOUT ); setCallback( callback ); editJob = jsJob; this.parentDialog = parentDialog; newSchedule = false; constructDialog( jsJob.getFullResourceName(), jsJob.getOutputPath(), jsJob.getJobName(), hasParams, isEmailConfValid, jsJob ); } public ScheduleRecurrenceDialog( PromptDialogBox parentDialog, String filePath, String outputLocation, String scheduleName, IDialogCallback callback, boolean hasParams, boolean isEmailConfValid ) { super( ScheduleDialogType.SCHEDULER, Messages.getString( "newSchedule" ), null, false, true ); //$NON-NLS-1$ isBlockoutDialog = false; setCallback( callback ); this.parentDialog = parentDialog; constructDialog( filePath, outputLocation, scheduleName, hasParams, isEmailConfValid, null ); } public ScheduleRecurrenceDialog( PromptDialogBox parentDialog, ScheduleDialogType type, String title, String filePath, String outputLocation, String scheduleName, IDialogCallback callback, boolean hasParams, boolean isEmailConfValid ) { super( type, title, null, false, true ); isBlockoutDialog = ( type == ScheduleDialogType.BLOCKOUT ); setCallback( callback ); this.parentDialog = parentDialog; constructDialog( filePath, outputLocation, scheduleName, hasParams, isEmailConfValid, null ); } @Override public boolean onKeyDownPreview( char key, int modifiers ) { if ( key == KeyCodes.KEY_ESCAPE ) { hide(); } return true; } public void setParentDialog( PromptDialogBox parentDialog ) { this.parentDialog = parentDialog; } public void addCustomPanel( Widget w, DockPanel.DockLayoutConstant position ) { scheduleEditorWizardPanel.add( w, position ); } private void constructDialog( String filePath, String outputLocation, String scheduleName, boolean hasParams, boolean isEmailConfValid, JsJob jsJob ) { this.hasParams = hasParams; this.filePath = filePath; this.isEmailConfValid = isEmailConfValid; this.outputLocation = outputLocation; this.scheduleName = scheduleName; scheduleEditorWizardPanel = new ScheduleEditorWizardPanel( getDialogType() ); scheduleEditor = scheduleEditorWizardPanel.getScheduleEditor(); String url = ScheduleHelper.getFullyQualifiedURL() + "api/scheduler/blockout/hasblockouts?ts=" + System.currentTimeMillis(); //$NON-NLS-1$ RequestBuilder hasBlockoutsRequest = new RequestBuilder( RequestBuilder.GET, url ); hasBlockoutsRequest.setHeader( "If-Modified-Since", "01 Jan 1970 00:00:00 GMT" ); hasBlockoutsRequest.setHeader( "accept", "text/plain" ); try { hasBlockoutsRequest.sendRequest( url, new RequestCallback() { @Override public void onError( Request request, Throwable exception ) { MessageDialogBox dialogBox = new MessageDialogBox( Messages.getString( "error" ), exception.toString(), false, false, true ); //$NON-NLS-1$ dialogBox.center(); } @Override public void onResponseReceived( Request request, Response response ) { Boolean hasBlockouts = Boolean.valueOf( response.getText() ); if ( hasBlockouts ) { scheduleEditor.setBlockoutButtonHandler( new ClickHandler() { @Override public void onClick( final ClickEvent clickEvent ) { PromptDialogBox box = new PromptDialogBox( Messages.getString( "blockoutTimes" ), Messages.getString( "close" ), null, null, false, true, new BlockoutPanel( false ) ); box.center(); } } ); } scheduleEditor.getBlockoutCheckButton().setVisible( hasBlockouts ); } } ); } catch ( RequestException e ) { MessageDialogBox dialogBox = new MessageDialogBox( Messages.getString( "error" ), e.toString(), //$NON-NLS-1$ false, false, true ); dialogBox.center(); } IWizardPanel[] wizardPanels = { scheduleEditorWizardPanel }; setWizardPanels( wizardPanels ); setPixelSize( 475, 465 ); center(); if ( ( hasParams || isEmailConfValid ) && ( isBlockoutDialog == false ) ) { finishButton.setText( Messages.getString( "next" ) ); //$NON-NLS-1$ } else { finishButton.setText( Messages.getString( "finish" ) ); //$NON-NLS-1$ } setupExisting( jsJob ); wizardDeckPanel.getElement().getParentElement().addClassName( "schedule-dialog-content" ); wizardDeckPanel.getElement().getParentElement().removeClassName( "dialog-content" ); //setHeight("100%"); //$NON-NLS-1$ setSize( "650px", "450px" ); addStyleName( "schedule-recurrence-dialog" ); } private void setupExisting( JsJob jsJob ) { if ( jsJob != null && !jsJob.equals( "" ) ) { //$NON-NLS-1$ JsJobTrigger jsJobTrigger = jsJob.getJobTrigger(); ScheduleType scheduleType = ScheduleType.valueOf( jsJobTrigger.getScheduleType() ); // scheduleEditor.setScheduleName(jsJob.getJobName()); scheduleEditor.setScheduleType( scheduleType ); if ( scheduleType == ScheduleType.CRON || jsJobTrigger.getType().equals( "cronJobTrigger" ) ) { //$NON-NLS-1$ scheduleEditor.getCronEditor().setCronString( jsJobTrigger.getCronString() ); } else if ( jsJobTrigger.getType().equals( "simpleJobTrigger" ) ) { //$NON-NLS-1$ if ( jsJobTrigger.getRepeatCount() == -1 ) { // Recurring simple Trigger int interval = jsJobTrigger.getRepeatInterval(); scheduleEditor.setRepeatInSecs( interval ); if ( scheduleType == ScheduleType.DAILY ) { DailyRecurrenceEditor dailyRecurrenceEditor = scheduleEditor.getRecurrenceEditor().getDailyEditor(); dailyRecurrenceEditor.setEveryNDays(); } } } else if ( jsJobTrigger.getType().equals( "complexJobTrigger" ) ) { //$NON-NLS-1$ if ( scheduleType == ScheduleType.DAILY ) { // Daily DailyRecurrenceEditor dailyRecurrenceEditor = scheduleEditor.getRecurrenceEditor().getDailyEditor(); if ( jsJobTrigger.isWorkDaysInWeek() ) { dailyRecurrenceEditor.setEveryWeekday(); } else { dailyRecurrenceEditor.setEveryNDays(); } } else if ( scheduleType == ScheduleType.WEEKLY ) { int[] daysOfWeek = jsJobTrigger.getDayOfWeekRecurrences(); WeeklyRecurrenceEditor weeklyRecurrenceEditor = scheduleEditor.getRecurrenceEditor().getWeeklyEditor(); String strDays = ""; //$NON-NLS-1$ for ( int element2 : daysOfWeek ) { strDays += Integer.toString( element2 ) + ","; //$NON-NLS-1$ } weeklyRecurrenceEditor.setCheckedDaysAsString( strDays, 1 ); } else if ( scheduleType == ScheduleType.MONTHLY ) { MonthlyRecurrenceEditor monthlyRecurrenceEditor = scheduleEditor.getRecurrenceEditor().getMonthlyEditor(); if ( jsJobTrigger.isQualifiedDayOfWeekRecurrence() ) { // Run Every on ___day of Nth week every month monthlyRecurrenceEditor.setDayOfWeek( TimeUtil.DayOfWeek.valueOf( jsJobTrigger.getQualifiedDayOfWeek() ) ); monthlyRecurrenceEditor .setWeekOfMonth( TimeUtil.WeekOfMonth.valueOf( jsJobTrigger.getDayOfWeekQualifier() ) ); monthlyRecurrenceEditor.setNthDayNameOfMonth(); } else { // Run on Nth day of the month monthlyRecurrenceEditor.setDayOfMonth( Integer.toString( jsJobTrigger.getDayOfMonthRecurrences()[0] ) ); } } else if ( scheduleType == ScheduleType.YEARLY ) { YearlyRecurrenceEditor yearlyRecurrenceEditor = scheduleEditor.getRecurrenceEditor().getYearlyEditor(); if ( jsJobTrigger.isQualifiedDayOfWeekRecurrence() ) { // Run Every on ___day of Nth week of the month M yearly yearlyRecurrenceEditor.setDayOfWeek( TimeUtil.DayOfWeek.valueOf( jsJobTrigger.getQualifiedDayOfWeek() ) ); yearlyRecurrenceEditor .setWeekOfMonth( TimeUtil.WeekOfMonth.valueOf( jsJobTrigger.getDayOfWeekQualifier() ) ); yearlyRecurrenceEditor.setMonthOfYear1( TimeUtil.MonthOfYear .get( jsJobTrigger.getMonthlyRecurrences()[0] - 1 ) ); yearlyRecurrenceEditor.setNthDayNameOfMonthName(); } else { // Run on Nth day of the month M yearly yearlyRecurrenceEditor.setDayOfMonth( Integer.toString( jsJobTrigger.getDayOfMonthRecurrences()[0] ) ); yearlyRecurrenceEditor.setMonthOfYear0( TimeUtil.MonthOfYear .get( jsJobTrigger.getMonthlyRecurrences()[0] - 1 ) ); yearlyRecurrenceEditor.setEveryMonthOnNthDay(); } } } scheduleEditor.setStartDate( jsJobTrigger.getStartTime() ); scheduleEditor.setStartTime( DateTimeFormat.getFormat( HOUR_MINUTE_SECOND ).format( jsJobTrigger.getStartTime() ) ); if ( jsJobTrigger.getEndTime() == null ) { scheduleEditor.setNoEndDate(); } else { scheduleEditor.setEndDate( jsJobTrigger.getEndTime() ); scheduleEditor.setEndBy(); } if ( isBlockoutDialog ) { scheduleEditor.setDurationFields( jsJobTrigger.getBlockDuration() ); } } } protected JSONObject getJsonSimpleTrigger( int repeatCount, int interval, Date startDate, Date endDate ) { JSONObject trigger = new JSONObject(); trigger.put( "uiPassParam", new JSONString( scheduleEditorWizardPanel.getScheduleType().name() ) ); //$NON-NLS-1$ trigger.put( "repeatInterval", new JSONNumber( interval ) ); //$NON-NLS-1$ trigger.put( "repeatCount", new JSONNumber( repeatCount ) ); //$NON-NLS-1$ addJsonStartEnd( trigger, startDate, endDate ); return trigger; } protected JSONObject getJsonCronTrigger( String cronString, Date startDate, Date endDate ) { JSONObject trigger = new JSONObject(); trigger.put( "uiPassParam", new JSONString( scheduleEditorWizardPanel.getScheduleType().name() ) ); //$NON-NLS-1$ trigger.put( "cronString", new JSONString( cronString ) ); //$NON-NLS-1$ addJsonStartEnd( trigger, startDate, endDate ); return trigger; } protected JSONObject getJsonComplexTrigger( ScheduleType scheduleType, MonthOfYear month, WeekOfMonth weekOfMonth, List<DayOfWeek> daysOfWeek, Date startDate, Date endDate ) { JSONObject trigger = new JSONObject(); trigger.put( "uiPassParam", new JSONString( scheduleEditorWizardPanel.getScheduleType().name() ) ); //$NON-NLS-1$ if ( month != null ) { JSONArray jsonArray = new JSONArray(); jsonArray.set( 0, new JSONString( Integer.toString( month.ordinal() ) ) ); trigger.put( "monthsOfYear", jsonArray ); //$NON-NLS-1$ } if ( weekOfMonth != null ) { JSONArray jsonArray = new JSONArray(); jsonArray.set( 0, new JSONString( Integer.toString( weekOfMonth.ordinal() ) ) ); trigger.put( "weeksOfMonth", jsonArray ); //$NON-NLS-1$ } if ( daysOfWeek != null ) { JSONArray jsonArray = new JSONArray(); int index = 0; for ( DayOfWeek dayOfWeek : daysOfWeek ) { jsonArray.set( index++, new JSONString( Integer.toString( dayOfWeek.ordinal() ) ) ); } trigger.put( "daysOfWeek", jsonArray ); //$NON-NLS-1$ } addJsonStartEnd( trigger, startDate, endDate ); return trigger; } protected JSONObject getJsonComplexTrigger( ScheduleType scheduleType, MonthOfYear month, int dayOfMonth, Date startDate, Date endDate ) { JSONObject trigger = new JSONObject(); trigger.put( "uiPassParam", new JSONString( scheduleEditorWizardPanel.getScheduleType().name() ) ); //$NON-NLS-1$ if ( month != null ) { JSONArray jsonArray = new JSONArray(); jsonArray.set( 0, new JSONString( Integer.toString( month.ordinal() ) ) ); trigger.put( "monthsOfYear", jsonArray ); //$NON-NLS-1$ } JSONArray jsonArray = new JSONArray(); jsonArray.set( 0, new JSONString( Integer.toString( dayOfMonth ) ) ); trigger.put( "daysOfMonth", jsonArray ); //$NON-NLS-1$ addJsonStartEnd( trigger, startDate, endDate ); return trigger; } /** * Returns an object suitable for posting into quartz via the the "JOB" rest service. * * @return */ @SuppressWarnings( "deprecation" ) public JSONObject getSchedule() { ScheduleType scheduleType = scheduleEditorWizardPanel.getScheduleType(); Date startDate = scheduleEditorWizardPanel.getStartDate(); String startTime = scheduleEditorWizardPanel.getStartTime(); // For blockout periods, we need the blockout start time. if ( isBlockoutDialog ) { startTime = scheduleEditorWizardPanel.getBlockoutStartTime(); } int startHour = getStartHour( startTime ); int startMin = getStartMin( startTime ); int startYear = startDate.getYear(); int startMonth = startDate.getMonth(); int startDay = startDate.getDate(); Date startDateTime = new Date( startYear, startMonth, startDay, startHour, startMin ); Date endDate = scheduleEditorWizardPanel.getEndDate(); MonthOfYear monthOfYear = scheduleEditor.getRecurrenceEditor().getSelectedMonth(); List<DayOfWeek> daysOfWeek = scheduleEditor.getRecurrenceEditor().getSelectedDaysOfWeek(); Integer dayOfMonth = scheduleEditor.getRecurrenceEditor().getSelectedDayOfMonth(); WeekOfMonth weekOfMonth = scheduleEditor.getRecurrenceEditor().getSelectedWeekOfMonth(); JSONObject schedule = new JSONObject(); schedule.put( "jobName", new JSONString( scheduleName ) ); //$NON-NLS-1$ if ( scheduleType == ScheduleType.RUN_ONCE ) { // Run once types schedule.put( "simpleJobTrigger", getJsonSimpleTrigger( 0, 0, startDateTime, null ) ); //$NON-NLS-1$ } else if ( ( scheduleType == ScheduleType.SECONDS ) || ( scheduleType == ScheduleType.MINUTES ) || ( scheduleType == ScheduleType.HOURS ) ) { int repeatInterval = 0; try { // Simple Trigger Types repeatInterval = Integer.parseInt( scheduleEditorWizardPanel.getRepeatInterval() ); } catch ( Exception e ) { // ignored } schedule.put( "simpleJobTrigger", getJsonSimpleTrigger( -1, repeatInterval, startDateTime, endDate ) ); //$NON-NLS-1$ } else if ( scheduleType == ScheduleType.DAILY ) { if ( scheduleEditor.getRecurrenceEditor().isEveryNDays() ) { int repeatInterval = 0; try { // Simple Trigger Types repeatInterval = Integer.parseInt( scheduleEditorWizardPanel.getRepeatInterval() ); } catch ( Exception e ) { // ignored } schedule.put( "simpleJobTrigger", getJsonSimpleTrigger( -1, repeatInterval, startDateTime, endDate ) ); //$NON-NLS-1$ } else { schedule .put( "complexJobTrigger", getJsonComplexTrigger( scheduleType, null, null, scheduleEditor.getRecurrenceEditor().getSelectedDaysOfWeek(), startDateTime, endDate ) ); //$NON-NLS-1$ } } else if ( scheduleType == ScheduleType.CRON ) { // Cron jobs schedule.put( "cronJobTrigger", getJsonCronTrigger( scheduleEditor.getCronString(), startDateTime, endDate ) ); //$NON-NLS-1$ } else if ( ( scheduleType == ScheduleType.WEEKLY ) && ( daysOfWeek.size() > 0 ) ) { schedule .put( "complexJobTrigger", getJsonComplexTrigger( scheduleType, null, null, scheduleEditor.getRecurrenceEditor().getSelectedDaysOfWeek(), startDateTime, endDate ) ); //$NON-NLS-1$ } else if ( ( scheduleType == ScheduleType.MONTHLY ) || ( ( scheduleType == ScheduleType.YEARLY ) && ( monthOfYear != null ) ) ) { if ( dayOfMonth != null ) { // YEARLY Run on specific day in year or MONTHLY Run on specific day in month schedule.put( "complexJobTrigger", getJsonComplexTrigger( scheduleType, monthOfYear, dayOfMonth, startDateTime, endDate ) ); } else if ( ( daysOfWeek.size() > 0 ) && ( weekOfMonth != null ) ) { // YEARLY schedule.put( "complexJobTrigger", getJsonComplexTrigger( scheduleType, monthOfYear, weekOfMonth, daysOfWeek, startDateTime, endDate ) ); } } schedule.put( "inputFile", new JSONString( filePath ) ); //$NON-NLS-1$ schedule.put( "outputFile", new JSONString( outputLocation ) ); //$NON-NLS-1$ return schedule; } @SuppressWarnings( "deprecation" ) private JSONObject addJsonStartEnd( JSONObject trigger, Date startDate, Date endDate ) { trigger.put( "startTime", new JSONString( DateTimeFormat.getFormat( PredefinedFormat.ISO_8601 ).format( startDate ) ) ); //$NON-NLS-1$ if ( endDate != null ) { endDate.setHours( 23 ); endDate.setMinutes( 59 ); endDate.setSeconds( 59 ); } trigger.put( "endTime", endDate == null ? JSONNull.getInstance() : new JSONString( DateTimeFormat.getFormat( PredefinedFormat.ISO_8601 ).format( endDate ) ) ); return trigger; } private long calculateBlockoutDuration() { long second = 1000; long minute = second * 60; long hour = minute * 60; long day = hour * 24; long durationMilli = -1; if ( scheduleEditor.getBlockoutEndsType().equals( ScheduleEditor.ENDS_TYPE.TIME ) ) { final String startTime = scheduleEditorWizardPanel.getBlockoutStartTime(); final String endTime = scheduleEditorWizardPanel.getBlockoutEndTime(); long start = getStartHour( startTime ) * hour + getStartMin( startTime ) * minute; long end = getStartHour( endTime ) * hour + getStartMin( endTime ) * minute; durationMilli = Math.abs( end - start ); } else { DurationValues durationValues = scheduleEditor.getDurationValues(); long minutes = durationValues.minutes * minute; long hours = durationValues.hours * hour; long days = durationValues.days * day; durationMilli = minutes + hours + days; } return durationMilli; } @SuppressWarnings( "deprecation" ) public JsJobTrigger getJsJobTrigger() { JsJobTrigger jsJobTrigger = JsJobTrigger.instance(); ScheduleType scheduleType = scheduleEditorWizardPanel.getScheduleType(); Date startDate = scheduleEditorWizardPanel.getStartDate(); String startTime = scheduleEditorWizardPanel.getStartTime(); int startHour = getStartHour( startTime ); int startMin = getStartMin( startTime ); int startYear = startDate.getYear(); int startMonth = startDate.getMonth(); int startDay = startDate.getDate(); Date startDateTime = new Date( startYear, startMonth, startDay, startHour, startMin ); Date endDate = scheduleEditorWizardPanel.getEndDate(); MonthOfYear monthOfYear = scheduleEditor.getRecurrenceEditor().getSelectedMonth(); List<DayOfWeek> daysOfWeek = scheduleEditor.getRecurrenceEditor().getSelectedDaysOfWeek(); Integer dayOfMonth = scheduleEditor.getRecurrenceEditor().getSelectedDayOfMonth(); WeekOfMonth weekOfMonth = scheduleEditor.getRecurrenceEditor().getSelectedWeekOfMonth(); if ( isBlockoutDialog ) { jsJobTrigger.setBlockDuration( calculateBlockoutDuration() ); } else { // blockDuration is only valid for blockouts jsJobTrigger.setBlockDuration( new Long( -1 ) ); } if ( scheduleType == ScheduleType.RUN_ONCE ) { // Run once types jsJobTrigger.setType( "simpleJobTrigger" ); //$NON-NLS-1$ jsJobTrigger.setRepeatInterval( 0 ); jsJobTrigger.setRepeatCount( 0 ); jsJobTrigger.setNativeStartTime( DateTimeFormat.getFormat( PredefinedFormat.ISO_8601 ).format( startDateTime ) ); } else if ( ( scheduleType == ScheduleType.SECONDS ) || ( scheduleType == ScheduleType.MINUTES ) || ( scheduleType == ScheduleType.HOURS ) ) { int repeatInterval = 0; try { // Simple Trigger Types repeatInterval = Integer.parseInt( scheduleEditorWizardPanel.getRepeatInterval() ); } catch ( Exception e ) { // ignored } jsJobTrigger.setType( "simpleJobTrigger" ); //$NON-NLS-1$ jsJobTrigger.setRepeatInterval( repeatInterval ); jsJobTrigger.setRepeatCount( -1 ); jsJobTrigger.setNativeStartTime( DateTimeFormat.getFormat( PredefinedFormat.ISO_8601 ).format( startDateTime ) ); if ( endDate != null ) { jsJobTrigger.setNativeEndTime( DateTimeFormat.getFormat( PredefinedFormat.ISO_8601 ).format( endDate ) ); } } else if ( scheduleType == ScheduleType.DAILY ) { if ( scheduleEditor.getRecurrenceEditor().isEveryNDays() ) { int repeatInterval = 0; try { // Simple Trigger Types repeatInterval = Integer.parseInt( scheduleEditorWizardPanel.getRepeatInterval() ); } catch ( Exception e ) { // ignored } jsJobTrigger.setType( "simpleJobTrigger" ); //$NON-NLS-1$ jsJobTrigger.setRepeatInterval( repeatInterval ); jsJobTrigger.setRepeatCount( -1 ); jsJobTrigger.setNativeStartTime( DateTimeFormat.getFormat( PredefinedFormat.ISO_8601 ).format( startDateTime ) ); if ( endDate != null ) { jsJobTrigger.setNativeEndTime( DateTimeFormat.getFormat( PredefinedFormat.ISO_8601 ).format( endDate ) ); } } else { JsArrayInteger jsDaysOfWeek = (JsArrayInteger) JavaScriptObject.createArray(); int i = 0; for ( DayOfWeek dayOfWeek : daysOfWeek ) { jsDaysOfWeek.set( i++, dayOfWeek.ordinal() + 1 ); } JsArrayInteger hours = (JsArrayInteger) JavaScriptObject.createArray(); hours.set( 0, startHour ); JsArrayInteger minutes = (JsArrayInteger) JavaScriptObject.createArray(); hours.set( 0, startMin ); JsArrayInteger seconds = (JsArrayInteger) JavaScriptObject.createArray(); hours.set( 0, 0 ); jsJobTrigger.setType( "complexJobTrigger" ); //$NON-NLS-1$ jsJobTrigger.setDayOfWeekRecurrences( jsDaysOfWeek ); jsJobTrigger.setHourRecurrences( hours ); jsJobTrigger.setMinuteRecurrences( minutes ); jsJobTrigger.setSecondRecurrences( seconds ); jsJobTrigger.setNativeStartTime( DateTimeFormat.getFormat( PredefinedFormat.ISO_8601 ).format( startDateTime ) ); if ( endDate != null ) { jsJobTrigger.setNativeEndTime( DateTimeFormat.getFormat( PredefinedFormat.ISO_8601 ).format( endDate ) ); } } } else if ( scheduleType == ScheduleType.CRON ) { // Cron jobs jsJobTrigger.setType( "cronJobTrigger" ); //$NON-NLS-1$ } else if ( ( scheduleType == ScheduleType.WEEKLY ) && ( daysOfWeek.size() > 0 ) ) { JsArrayInteger jsDaysOfWeek = (JsArrayInteger) JavaScriptObject.createArray(); int i = 0; for ( DayOfWeek dayOfWeek : daysOfWeek ) { jsDaysOfWeek.set( i++, dayOfWeek.ordinal() + 1 ); } JsArrayInteger hours = (JsArrayInteger) JavaScriptObject.createArray(); hours.set( 0, startHour ); JsArrayInteger minutes = (JsArrayInteger) JavaScriptObject.createArray(); hours.set( 0, startMin ); JsArrayInteger seconds = (JsArrayInteger) JavaScriptObject.createArray(); hours.set( 0, 0 ); jsJobTrigger.setType( "complexJobTrigger" ); //$NON-NLS-1$ jsJobTrigger.setDayOfWeekRecurrences( jsDaysOfWeek ); jsJobTrigger.setHourRecurrences( hours ); jsJobTrigger.setMinuteRecurrences( minutes ); jsJobTrigger.setSecondRecurrences( seconds ); jsJobTrigger.setNativeStartTime( DateTimeFormat.getFormat( PredefinedFormat.ISO_8601 ).format( startDateTime ) ); if ( endDate != null ) { jsJobTrigger.setNativeEndTime( DateTimeFormat.getFormat( PredefinedFormat.ISO_8601 ).format( endDate ) ); } } else if ( ( scheduleType == ScheduleType.MONTHLY ) || ( ( scheduleType == ScheduleType.YEARLY ) && ( monthOfYear != null ) ) ) { jsJobTrigger.setType( "complexJobTrigger" ); //$NON-NLS-1$ if ( dayOfMonth != null ) { JsArrayInteger jsDaysOfMonth = (JsArrayInteger) JavaScriptObject.createArray(); jsDaysOfMonth.set( 0, dayOfMonth ); JsArrayInteger hours = (JsArrayInteger) JavaScriptObject.createArray(); hours.set( 0, startHour ); JsArrayInteger minutes = (JsArrayInteger) JavaScriptObject.createArray(); hours.set( 0, startMin ); JsArrayInteger seconds = (JsArrayInteger) JavaScriptObject.createArray(); hours.set( 0, 0 ); jsJobTrigger.setType( "complexJobTrigger" ); //$NON-NLS-1$ if ( monthOfYear != null ) { JsArrayInteger jsMonthsOfYear = (JsArrayInteger) JavaScriptObject.createArray(); jsMonthsOfYear.set( 0, monthOfYear.ordinal() + 1 ); jsJobTrigger.setMonthlyRecurrences( jsMonthsOfYear ); } jsJobTrigger.setDayOfMonthRecurrences( jsDaysOfMonth ); jsJobTrigger.setHourRecurrences( hours ); jsJobTrigger.setMinuteRecurrences( minutes ); jsJobTrigger.setSecondRecurrences( seconds ); jsJobTrigger.setNativeStartTime( DateTimeFormat.getFormat( PredefinedFormat.ISO_8601 ).format( startDateTime ) ); if ( endDate != null ) { jsJobTrigger.setNativeEndTime( DateTimeFormat.getFormat( PredefinedFormat.ISO_8601 ).format( endDate ) ); } } else if ( ( daysOfWeek.size() > 0 ) && ( weekOfMonth != null ) ) { JsArrayInteger jsDaysOfWeek = (JsArrayInteger) JavaScriptObject.createArray(); int i = 0; for ( DayOfWeek dayOfWeek : daysOfWeek ) { jsDaysOfWeek.set( i++, dayOfWeek.ordinal() + 1 ); } JsArrayInteger hours = (JsArrayInteger) JavaScriptObject.createArray(); hours.set( 0, startHour ); JsArrayInteger minutes = (JsArrayInteger) JavaScriptObject.createArray(); hours.set( 0, startMin ); JsArrayInteger seconds = (JsArrayInteger) JavaScriptObject.createArray(); hours.set( 0, 0 ); jsJobTrigger.setType( "complexJobTrigger" ); //$NON-NLS-1$ if ( monthOfYear != null ) { JsArrayInteger jsMonthsOfYear = (JsArrayInteger) JavaScriptObject.createArray(); jsMonthsOfYear.set( 0, monthOfYear.ordinal() + 1 ); jsJobTrigger.setMonthlyRecurrences( jsMonthsOfYear ); } jsJobTrigger.setHourRecurrences( hours ); jsJobTrigger.setMinuteRecurrences( minutes ); jsJobTrigger.setSecondRecurrences( seconds ); jsJobTrigger.setQualifiedDayOfWeek( daysOfWeek.get( 0 ).name() ); jsJobTrigger.setDayOfWeekQualifier( weekOfMonth.name() ); jsJobTrigger.setNativeStartTime( DateTimeFormat.getFormat( PredefinedFormat.ISO_8601 ).format( startDateTime ) ); if ( endDate != null ) { jsJobTrigger.setNativeEndTime( DateTimeFormat.getFormat( PredefinedFormat.ISO_8601 ).format( endDate ) ); } } } return jsJobTrigger; } protected boolean addBlockoutPeriod( final JSONObject schedule, final JsJobTrigger trigger, String urlSuffix ) { String url = ScheduleHelper.getFullyQualifiedURL() + "api/scheduler/blockout/" + urlSuffix; //$NON-NLS-1$ RequestBuilder addBlockoutPeriodRequest = new RequestBuilder( RequestBuilder.POST, url ); addBlockoutPeriodRequest.setHeader( "accept", "text/plain" ); //$NON-NLS-1$ //$NON-NLS-2$ addBlockoutPeriodRequest.setHeader( "Content-Type", "application/json" ); //$NON-NLS-1$ //$NON-NLS-2$ addBlockoutPeriodRequest.setHeader( "If-Modified-Since", "01 Jan 1970 00:00:00 GMT" ); // Create a unique blockout period name final Long duration = trigger.getBlockDuration(); final String blockoutPeriodName = trigger.getScheduleType() + Random.nextInt() + ":" + //$NON-NLS-1$ /* PentahoSessionHolder.getSession().getName() */"admin" + ":" + duration; //$NON-NLS-1$ //$NON-NLS-2$ // Add blockout specific parameters JSONObject addBlockoutParams = schedule; addBlockoutParams.put( "jobName", new JSONString( blockoutPeriodName ) ); //$NON-NLS-1$ addBlockoutParams.put( "duration", new JSONNumber( duration ) ); //$NON-NLS-1$ addBlockoutParams.put( "timeZone", new JSONString( scheduleEditorWizardPanel.getTimeZone() ) ); try { addBlockoutPeriodRequest.sendRequest( addBlockoutParams.toString(), new RequestCallback() { @Override public void onError( Request request, Throwable exception ) { MessageDialogBox dialogBox = new MessageDialogBox( Messages.getString( "error" ), exception.toString(), false, false, true ); //$NON-NLS-1$ dialogBox.center(); setDone( false ); } @Override public void onResponseReceived( Request request, Response response ) { if ( response.getStatusCode() == Response.SC_OK ) { if ( null != callback ) { callback.okPressed(); } } } } ); } catch ( RequestException e ) { // ignored } return true; } private void promptDueToBlockoutConflicts( final boolean alwaysConflict, final boolean conflictsSometimes, final JSONObject schedule, final JsJobTrigger trigger ) { StringBuffer conflictMessage = new StringBuffer(); final String updateScheduleButtonText = Messages.getString( "blockoutUpdateSchedule" ); //$NON-NLS-1$ final String continueButtonText = Messages.getString( "blockoutContinueSchedule" ); //$NON-NLS-1$ boolean showContinueButton = conflictsSometimes; boolean isScheduleConflict = alwaysConflict || conflictsSometimes; if ( conflictsSometimes ) { conflictMessage.append( Messages.getString( "blockoutPartialConflict" ) ); //$NON-NLS-1$ conflictMessage.append( "\n" ); //$NON-NLS-1$ conflictMessage.append( Messages.getString( "blockoutPartialConflictContinue" ) ); //$NON-NLS-1$ } else { conflictMessage.append( Messages.getString( "blockoutTotalConflict" ) ); //$NON-NLS-1$ } if ( isScheduleConflict ) { final MessageDialogBox dialogBox = new MessageDialogBox( Messages.getString( "blockoutTimeExists" ), //$NON-NLS-1$ conflictMessage.toString(), false, false, true, updateScheduleButtonText, showContinueButton ? continueButtonText : null, null ); dialogBox.setCallback( new IDialogCallback() { // If user clicked on 'Continue' we want to add the schedule. Otherwise we dismiss the dialog // and they have to modify the recurrence schedule @Override public void cancelPressed() { // User clicked on continue, so we need to proceed adding the schedule handleWizardPanels( schedule, trigger ); } @Override public void okPressed() { // Update Schedule Button pressed dialogBox.setVisible( false ); } } ); dialogBox.center(); } } /** * Before creating a new schedule, we want to check to see if the schedule that is being created is going to conflict * with any one of the blockout periods if one is provisioned. * * @param schedule * @param trigger */ protected void verifyBlockoutConflict( final JSONObject schedule, final JsJobTrigger trigger ) { String url = ScheduleHelper.getFullyQualifiedURL() + "api/scheduler/blockout/blockstatus"; //$NON-NLS-1$ RequestBuilder blockoutConflictRequest = new RequestBuilder( RequestBuilder.POST, url ); blockoutConflictRequest.setHeader( "accept", "application/json" ); //$NON-NLS-1$ //$NON-NLS-2$ blockoutConflictRequest.setHeader( "Content-Type", "application/json" ); //$NON-NLS-1$ //$NON-NLS-2$ blockoutConflictRequest.setHeader( "If-Modified-Since", "01 Jan 1970 00:00:00 GMT" ); final JSONObject verifyBlockoutParams = schedule; verifyBlockoutParams.put( "jobName", new JSONString( scheduleName ) ); //$NON-NLS-1$ try { blockoutConflictRequest.sendRequest( verifyBlockoutParams.toString(), new RequestCallback() { @Override public void onError( Request request, Throwable exception ) { MessageDialogBox dialogBox = new MessageDialogBox( Messages.getString( "error" ), exception.toString(), false, false, true ); //$NON-NLS-1$ dialogBox.center(); setDone( false ); } @Override public void onResponseReceived( Request request, Response response ) { if ( response.getStatusCode() == Response.SC_OK ) { JsBlockStatus statusResponse = (JsBlockStatus) parseJson( JsonUtils.escapeJsonForEval( response.getText() ) ); // Determine if this schedule conflicts all the time or some of the time boolean partiallyBlocked = Boolean.parseBoolean( statusResponse.getPartiallyBlocked() ); boolean totallyBlocked = Boolean.parseBoolean( statusResponse.getTotallyBlocked() ); if ( partiallyBlocked || totallyBlocked ) { promptDueToBlockoutConflicts( totallyBlocked, partiallyBlocked, schedule, trigger ); } else { // Continue with other panels in the wizard (params, email) handleWizardPanels( schedule, trigger ); } } else { handleWizardPanels( schedule, trigger ); } } } ); } catch ( RequestException e ) { // ignored } super.nextClicked(); } private void handleWizardPanels( final JSONObject schedule, final JsJobTrigger trigger ) { if ( hasParams ) { showScheduleParamsDialog( trigger, schedule ); } else if ( isEmailConfValid ) { showScheduleEmailDialog( schedule ); } else { // submit JSONObject scheduleRequest = (JSONObject) JSONParser.parseStrict( schedule.toString() ); if ( editJob != null ) { JSONArray scheduleParams = new JSONArray(); for ( int i = 0; i < editJob.getJobParams().length(); i++ ) { JsJobParam param = editJob.getJobParams().get( i ); JsArrayString paramValue = (JsArrayString) JavaScriptObject.createArray().cast(); paramValue.push( param.getValue() ); JsSchedulingParameter p = (JsSchedulingParameter) JavaScriptObject.createObject().cast(); p.setName( param.getName() ); p.setType( "string" ); //$NON-NLS-1$ p.setStringValue( paramValue ); scheduleParams.set( i, new JSONObject( p ) ); } scheduleRequest.put( "jobParameters", scheduleParams ); //$NON-NLS-1$ String actionClass = editJob.getJobParamValue( "ActionAdapterQuartzJob-ActionClass" ); //$NON-NLS-1$ if ( !StringUtils.isEmpty( actionClass ) ) { scheduleRequest.put( "actionClass", new JSONString( actionClass ) ); //$NON-NLS-1$ } } RequestBuilder scheduleFileRequestBuilder = ScheduleHelper.buildRequestForJob( editJob, scheduleRequest ); try { scheduleFileRequestBuilder.sendRequest( scheduleRequest.toString(), new RequestCallback() { @Override public void onError( Request request, Throwable exception ) { MessageDialogBox dialogBox = new MessageDialogBox( Messages.getString( "error" ), exception.toString(), false, false, true ); //$NON-NLS-1$ dialogBox.center(); setDone( false ); } @Override public void onResponseReceived( Request request, Response response ) { if ( response.getStatusCode() == 200 ) { setDone( true ); ScheduleRecurrenceDialog.this.hide(); if ( callback != null ) { callback.okPressed(); } } else { MessageDialogBox dialogBox = new MessageDialogBox( Messages.getString( "error" ), //$NON-NLS-1$ Messages.getString( "serverErrorColon" ) + " " + response.getStatusCode(), false, false, true ); dialogBox.center(); setDone( false ); } } } ); } catch ( RequestException e ) { MessageDialogBox dialogBox = new MessageDialogBox( Messages.getString( "error" ), e.toString(), //$NON-NLS-1$ false, false, true ); dialogBox.center(); setDone( false ); } setDone( true ); } } private final native JavaScriptObject parseJson( String json ) /*-{ if (null == json || "" == json) { return null; } var obj = JSON.parse(json); return obj; }-*/; /* * (non-Javadoc) * * @see org.pentaho.gwt.widgets.client.wizards.AbstractWizardDialog#finish() */ @Override protected boolean onFinish() { if ( !super.enableFinish( getIndex() ) ) { return false; } // DO NOT DELETE - verifyBlockoutConflict(schedule, trigger); JsJobTrigger trigger = getJsJobTrigger(); JSONObject schedule = getSchedule(); handleWizardPanels( schedule, trigger ); return true; } private void showScheduleEmailDialog( final JSONObject schedule ) { try { final String url = ScheduleHelper.getFullyQualifiedURL() + "api/mantle/isAuthenticated"; //$NON-NLS-1$ RequestBuilder requestBuilder = new RequestBuilder( RequestBuilder.GET, url ); requestBuilder.setHeader( "accept", "text/plain" ); //$NON-NLS-1$ //$NON-NLS-2$ requestBuilder.setHeader( "If-Modified-Since", "01 Jan 1970 00:00:00 GMT" ); requestBuilder.sendRequest( null, new RequestCallback() { @Override public void onError( Request request, Throwable caught ) { MantleLoginDialog.performLogin( new AsyncCallback<Boolean>() { @Override public void onFailure( Throwable caught ) { } @Override public void onSuccess( Boolean result ) { showScheduleEmailDialog( schedule ); } } ); } @Override public void onResponseReceived( Request request, Response response ) { JSONObject scheduleRequest = (JSONObject) JSONParser.parseStrict( schedule.toString() ); if ( scheduleEmailDialog == null ) { scheduleEmailDialog = new ScheduleEmailDialog( ScheduleRecurrenceDialog.this, filePath, scheduleRequest, null, editJob ); scheduleEmailDialog.setCallback( callback ); } else { scheduleEmailDialog.setJobSchedule( scheduleRequest ); } scheduleEmailDialog.setNewSchedule( newSchedule ); scheduleEmailDialog.center(); hide(); } } ); } catch ( RequestException e ) { Window.alert( e.getMessage() ); } } private void showScheduleParamsDialog( final JsJobTrigger trigger, final JSONObject schedule ) { try { final String url = ScheduleHelper.getFullyQualifiedURL() + "api/mantle/isAuthenticated"; //$NON-NLS-1$ RequestBuilder requestBuilder = new RequestBuilder( RequestBuilder.GET, url ); requestBuilder.setHeader( "accept", "text/plain" ); //$NON-NLS-1$ //$NON-NLS-2$ requestBuilder.setHeader( "If-Modified-Since", "01 Jan 1970 00:00:00 GMT" ); requestBuilder.sendRequest( null, new RequestCallback() { @Override public void onError( Request request, Throwable caught ) { MantleLoginDialog.performLogin( new AsyncCallback<Boolean>() { @Override public void onFailure( Throwable caught ) { } @Override public void onSuccess( Boolean result ) { showScheduleParamsDialog( trigger, schedule ); } } ); } @Override public void onResponseReceived( Request request, Response response ) { if ( scheduleParamsDialog == null ) { scheduleParamsDialog = new ScheduleParamsDialog( ScheduleRecurrenceDialog.this, isEmailConfValid, editJob ); scheduleParamsDialog.setCallback( callback ); } else { scheduleParamsDialog.setJobSchedule( schedule ); } scheduleParamsDialog.setNewSchedule( newSchedule ); scheduleParamsDialog.center(); hide(); } } ); } catch ( RequestException e ) { Window.alert( e.getMessage() ); } } /** * @param startTime * @return */ private int getStartMin( String startTime ) { if ( startTime == null || startTime.length() < 1 ) { return 0; } int firstSeparator = startTime.indexOf( ':' ); int secondSeperator = startTime.indexOf( ':', firstSeparator + 1 ); int min = Integer.parseInt( startTime.substring( firstSeparator + 1, secondSeperator ) ); return min; } /** * @param startTime * @return */ private int getStartHour( String startTime ) { if ( startTime == null || startTime.length() < 1 ) { return 0; } int afternoonOffset = startTime.endsWith( TimeUtil.TimeOfDay.PM.toString() ) ? 12 : 0; //$NON-NLS-1$ int hour = Integer.parseInt( startTime.substring( 0, startTime.indexOf( ':' ) ) ); hour += afternoonOffset; return hour; } public Boolean getDone() { return done; } public void setDone( Boolean done ) { this.done = done; } /* * (non-Javadoc) * * @see org.pentaho.gwt.widgets.client.wizards.AbstractWizardDialog#onNext(org.pentaho.gwt.widgets.client.wizards. * IWizardPanel, org.pentaho.gwt.widgets.client.wizards.IWizardPanel) */ @Override protected boolean onNext( IWizardPanel nextPanel, IWizardPanel previousPanel ) { return super.enableNext( getIndex() ); } /* * (non-Javadoc) * * @see org.pentaho.gwt.widgets.client.wizards.AbstractWizardDialog#onPrevious(org.pentaho.gwt.widgets.client.wizards * .IWizardPanel, org.pentaho.gwt.widgets.client.wizards.IWizardPanel) */ @Override protected boolean onPrevious( IWizardPanel previousPanel, IWizardPanel currentPanel ) { return true; } @Override protected void backClicked() { hide(); if ( parentDialog != null ) { parentDialog.center(); } } @Override public void center() { super.center(); Timer t = new Timer() { @Override public void run() { if ( scheduleEditorWizardPanel.isAttached() && scheduleEditorWizardPanel.isVisible() ) { cancel(); } } }; t.scheduleRepeating( 250 ); } @Override protected boolean enableBack( int index ) { return parentDialog != null; } @Override protected boolean showBack( int index ) { return parentDialog != null; } @Override protected boolean showFinish( int index ) { return true; } @Override protected boolean showNext( int index ) { return false; } public void setCallback( IDialogCallback callback ) { this.callback = callback; } public IDialogCallback getCallback() { return callback; } public boolean isShowSuccessDialog() { return showSuccessDialog; } public void setShowSuccessDialog( boolean showSuccessDialog ) { this.showSuccessDialog = showSuccessDialog; } public void setNewSchedule( boolean newSchedule ) { this.newSchedule = newSchedule; } }